const { Readable } = require("stream");
const _ = require("lodash");
const moment = require("moment");
const fs = require("fs");
const utils = require('../../utils');

module.exports = async function (file, options) {
  const stream = new Readable({ objectMode: true });
  options = utils.parseFunction(options);
  let needSplit, sep, keepEmpty, inFormat, format, encoding = _.get(options, 'encoding', 'utf-8'), isText = _.get(options, 'isText');
  const text = fs.readFileSync(file, encoding);
  if (isText) {
    needSplit = false;
  } else if (!options) {
    needSplit = true;
  } else if (options === 1 || options === true) {
    needSplit = false;
  } else if (_.isFunction(options)) {
    text = formatText(text, { _, moment, utils });
    needSplit = false;
  } else if (_.isString(options)) {
    needSplit = true;
    sep = options;
  } else {
    needSplit = true;
    sep = options.sep;
    keepEmpty = utils.parseFunction(options.keepEmpty);
    inFormat = utils.parseFunction(options.inFormat);
    format = utils.parseFunction(options.format);
  }

  let list, rowNo = 0;
  if (needSplit) {
    let _list;
    const r = utils.eval(text);
    if (!r.error && _.isArray(r.value)) {
      _list = r.value;
    } else {
      if (sep) {
        _list = text.split(sep);
      } else if (/\n/.test(text)) {
        _list = text.split(/\r?\n/);
      } else {
        _list = text.split(/\s+|，|,|；|;/);
      }
      _list = _list.map(o => o.trim());
    }
    !keepEmpty && (_list = _list.filter(Boolean));
    list = format ? await format(_list, { _, moment, utils }) : _list;
  }
  stream._read = async function () {
    if (needSplit) {
      if (rowNo < list.length) {
        stream.push(inFormat ? inFormat(list[rowNo], { _, moment, utils }) : list[rowNo]);
      } else {
        stream.push(null);
      }
      rowNo++;
    } else {
      stream.push(text);
      stream.push(null);
    }
  };

  stream.on('end', () => {
    utils.debug('fileReader [end]');
  });
  
  return stream;
}